package cn.yunyichina.provider.pay.wechat.service.impl;

import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.pay.wechat.common.XMLUtil;
import cn.yunyichina.provider.pay.wechat.config.Wechat;
import cn.yunyichina.provider.pay.wechat.constant.ResponseEnum;
import cn.yunyichina.provider.pay.wechat.entity.WechatAppletOpenidRequest;
import cn.yunyichina.provider.pay.wechat.entity.WechatAppletOpenidResponse;
import cn.yunyichina.provider.pay.wechat.entity.WechatAppletPayRequest;
import cn.yunyichina.provider.pay.wechat.entity.WechatAppletPayResponse;
import cn.yunyichina.provider.pay.wechat.entity.common.WechatCommonResponse;
import cn.yunyichina.provider.pay.wechat.service.BaseAppletService;
import cn.yunyichina.provider.pay.wechat.service.WechatAppletService;
import cn.yunyichina.utils.commons.HttpUtil;
import cn.yunyichina.utils.convert.JsonUtils;
import cn.yunyichina.utils.security.SignUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Map;

/**
 * Created by Lullaby on 2016/12/10.
 */
@Service
public class WechatAppletServiceImpl extends BaseAppletService implements WechatAppletService {

    private static final Logger logger = LoggerFactory.getLogger(WechatAppletServiceImpl.class);

    /**
     * 获取微信小程序openid
     *
     * @param json
     * @return
     */
    public ResponseObject getWechatAppletOpenid(String json) {
        ResponseObject response = new ResponseObject();

        logger.info("WechatAppletServiceImpl.getWechatAppletOpenid.json -> {}", json);

        WechatAppletOpenidRequest openidRequest = JsonUtils.parseObject(json, WechatAppletOpenidRequest.class);

        String requestUrl = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=" + openidRequest.getAppid() +
                "&secret=" + openidRequest.getSecret() +
                "&js_code=" + openidRequest.getJsCode() +
                "&grant_type=" + openidRequest.getGrantType();

        logger.info("WechatAppletServiceImpl.getWechatAppletOpenid.requestUrl -> {}", requestUrl);

        try {
            String httpGetResult = HttpUtil.get(requestUrl);

            logger.info("WechatAppletServiceImpl.getWechatAppletOpenid.httpGetResult -> {}", httpGetResult);

            WechatAppletOpenidResponse openidResponse = JsonUtils.parseObject(httpGetResult, WechatAppletOpenidResponse.class);

            if (openidResponse != null && !StringUtils.isEmpty(openidResponse.getOpenid())) {
                response.setResultObject(openidResponse);
            } else {
                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_APPLET_OPENID_FAILURE.getCode(),
                        ResponseEnum.WECHAT_APPLET_OPENID_FAILURE.getMessage(),
                        getWechatErrcodeAndmsg(JsonUtils.parseObject(httpGetResult, WechatCommonResponse.class))
                );
            }
        } catch (IOException e) {
            logger.error("WechatAppletServiceImpl.getWechatAppletOpenid.exception", e);

            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_APPLET_OPENID_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_APPLET_OPENID_EXCEPTION.getMessage()
            );
        }

        return response;
    }

    /**
     * 微信小程序支付统一下单
     *
     * @param json
     * @return
     */
    public ResponseObject payWechatApplet(String json) {
        logger.info("WechatAppletServiceImpl.payWechatApplet.json -> {}", json);

        ResponseObject response = new ResponseObject();

        try {
            WechatAppletPayRequest payRequest = JsonUtils.parseObject(json, WechatAppletPayRequest.class);

            String apiSecret = payRequest.getApiSecret();
            payRequest.setApiSecret(null);
            payRequest.setSign(SignUtil.wechatPaySign(JsonUtils.parseObject(payRequest, Map.class), apiSecret));

            String xml = XMLUtil.buildMapXML(JsonUtils.parseObject(payRequest, Map.class));
            logger.info("WechatAppletServiceImpl.payWechatApplet.xml -> {}", xml);

            String result = HttpUtil.post(xml, this.getConfig(Wechat.WECHAT_PAY_PAY_UNIFIED));
            logger.info("WechatAppletServiceImpl.payWechatApplet.result -> {}", result);

            Map<String, String> resultMap = XMLUtil.xmlToMap(result);
            WechatAppletPayResponse appletPayResponse = JsonUtils.parseObject(resultMap, WechatAppletPayResponse.class);

            if (appletPayResponse.isReturnCodeSuccess()) {
                if (SignUtil.validateWechatPaySign(resultMap, apiSecret)) {
                    if (appletPayResponse.isResultCodeSuccess()) {

                        response.setResultObject(buildAppletPayResponse(appletPayResponse, apiSecret));

                    } else {
                        logger.warn("WechatAppletServiceImpl.payWechatApplet.resultCode -> {}", appletPayResponse.getResultCode());

                        response.setResultCodeAndMessageAndResult(
                                ResponseEnum.WECHAT_PAY_FAIL.getCode(),
                                ResponseEnum.WECHAT_PAY_FAIL.getMessage(),
                                getWechatErrCodeAndDes(JsonUtils.parseObject(appletPayResponse, WechatCommonResponse.class))
                        );
                    }
                } else {
                    response.setResultCodeAndMessage(
                            ResponseEnum.WECHAT_INVALID_SIGN.getCode(),
                            ResponseEnum.WECHAT_INVALID_SIGN.getMessage()
                    );
                }
            } else {
                logger.warn("WechatAppletServiceImpl.payWechatApplet.returnCode -> {}", appletPayResponse.getReturnCode());

                response.setResultCodeAndMessageAndResult(
                        ResponseEnum.WECHAT_PAY_FAIL.getCode(),
                        ResponseEnum.WECHAT_PAY_FAIL.getMessage(),
                        getWechatReturnCodeAndMsg(JsonUtils.parseObject(appletPayResponse, WechatCommonResponse.class))
                );
            }
        } catch (Exception e) {
            logger.error("WechatAppletServiceImpl.payWechatApplet.exception", e);

            response.setResultCodeAndMessage(
                    ResponseEnum.WECHAT_PAY_EXCEPTION.getCode(),
                    ResponseEnum.WECHAT_PAY_EXCEPTION.getMessage()
            );
        }

        return response;
    }

}
